package org.pp.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.CloseOrderRequest;
import org.pp.config.WechatPayConfig;
import org.pp.core.*;
import org.pp.entity.PpOrder;
import org.pp.entity.PpOrderItem;
import org.pp.entity.PpUserAddress;
import org.pp.mapper.PpOrderMapper;
import org.pp.miniapp.dto.CartAdd;
import org.pp.miniapp.dto.OrderAdd;
import org.pp.miniapp.dto.OrderPage;
import org.pp.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.pp.store.OssStore;
import org.pp.util.PageUtil;
import org.pp.vo.MiniappOrderDetailVo;
import org.pp.vo.MiniappOrderVo;
import org.pp.vo.MiniappOrderItemVo;
import org.pp.vo.MiniappPreOrderVo;
import org.redisson.api.RDelayedQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 商品订单表 服务实现类
 * </p>
 *
 * @author haima
 * @since 2024-10-07
 */
@Service
public class PpOrderServiceImpl extends ServiceImpl<PpOrderMapper, PpOrder> implements IPpOrderService {

    @Autowired
    IPpGoodsSkuService skuService;

    @Autowired
    IPpPublicConfigService configService;

    @Autowired
    IPpOrderItemService itemService;

    @Autowired
    IPpCartService cartService;

    @Autowired
    OssStore ossStore;

    @Autowired
    RSAAutoCertificateConfig certificateConfig;

    @Autowired
    WechatPayConfig config;

    @Autowired
    IPpUserAddressService addressService;

    @Autowired
    RDelayedQueue<String> queue;


    @Override
    public MiniappPreOrderVo prepare(List<Long> cartIds) {
        List<MiniappOrderItemVo> items = getMiniappPpOrderItemVos(cartIds);
        items.forEach(e->e.setCover(ossStore.getUrl(e.getCover())));
        MiniappPreOrderVo vo= new MiniappPreOrderVo();
        vo.setItems(items);
        vo.setTotalPrice(items.stream().map(MiniappOrderItemVo::getTotallPrice).reduce(BigDecimal.ZERO,BigDecimal::add));
        vo.setTotalPostage(items.stream().map(MiniappOrderItemVo::getTotallPostage).reduce(BigDecimal.ZERO,BigDecimal::add));
        vo.setTotalAmount(items.stream().mapToInt(MiniappOrderItemVo::getAmount).sum());
        vo.setPayPrice(vo.getTotalPrice().add(vo.getTotalPostage()));
        return vo;
    }

    private List<MiniappOrderItemVo> getMiniappPpOrderItemVos(List<Long> cartIds) {
        List<MiniappOrderItemVo> items= skuService.listOrderItemByCartId(cartIds);
        if(!Objects.equals(items.size(), cartIds.size())){
            throw BizExcept.erro("条目id错误");
        }
        String freeFrom = configService.getConfigByName(Constants.sysFreeFrom);
        BigDecimal overTatalPrice= BigDecimal.ZERO;
        for (MiniappOrderItemVo item : items) {
            item.setPostageThreshold(new BigDecimal(freeFrom));
            if(!Objects.equals(MiniappSessionUtil.getUserId(),item.getUserId())){
                throw BizExcept.erro("条目id错误");
            }
            if(item.getAmount()>item.getStock()){
                throw BizExcept.erro("库存不足");
            }
            item.setTotallPrice(item.getPrice().multiply(BigDecimal.valueOf(item.getAmount())));
            item.setAttrInfoStr(CollUtil.join(item.getAttrInfo().values(),","));
            if(item.getPostageIfFree()|| Objects.isNull(item.getPostage())|| item.getPostage().compareTo(BigDecimal.ZERO)==0){
                item.setTotallPostage(BigDecimal.ZERO);
                item.setTotallPostageDesc("包邮");
            }else{
                if(item.getPostageSkuIfMerge()){
                    item.setTotallPostage(item.getPostage());
                    item.setTotallPostageDesc("同规格合并邮寄");
                }else{
                    item.setTotallPostage(item.getPostage().multiply(BigDecimal.valueOf(item.getAmount())));
                }
                if(item.getPostageInRuleIfFree()){
                    overTatalPrice= overTatalPrice.add(item.getTotallPrice());
                }
            }
        }

        for (MiniappOrderItemVo item : items) {
            if(item.getPostageInRuleIfFree()&& overTatalPrice.compareTo(new BigDecimal(freeFrom))>0){
                item.setTotallPostage(BigDecimal.ZERO);
                item.setTotallPostageDesc(StrUtil.format("满￥{}包邮",freeFrom));
            }
           // item.setCover(ossStore.getUrl(item.getCover()));
        }
        return items;
    }

    @Override
    @Transactional
    public String create(OrderAdd dto) {

        List<MiniappOrderItemVo> items = getMiniappPpOrderItemVos(dto.getCartIds());
        PpOrder order= new PpOrder();
        order.setUserId(MiniappSessionUtil.getUserId());
        order.setGoodsPrice(items.stream().map(MiniappOrderItemVo::getTotallPrice).reduce(BigDecimal.ZERO,BigDecimal::add));
        order.setPostage(items.stream().map(MiniappOrderItemVo::getTotallPostage).reduce(BigDecimal.ZERO,BigDecimal::add));
        order.setAmount(items.stream().mapToInt(MiniappOrderItemVo::getAmount).sum());
        order.setPayPrice(order.getGoodsPrice().add(order.getPostage()));
        order.setOrderNo(IdUtil.fastSimpleUUID());
        order.setNames(CollUtil.join(items.stream().map(e->e.getName()).toList(),","));

        List<PpOrder.ItemInfo> itemInfos = BeanUtil.copyToList(items, PpOrder.ItemInfo.class);
        order.setItemInfo(itemInfos.toArray(new PpOrder.ItemInfo[0]));
        List<PpOrderItem> orderItems = BeanUtil.copyToList(items, PpOrderItem.class);

        PpUserAddress address = addressService.getById(dto.getAddressId());
        Assertion.nullThrow(address,"地址不存在");
        order.setPostAddress(BeanUtil.copyProperties(address,PpOrder.PostAddress.class));

        save(order);
        orderItems.forEach(e->e.setOrderId(order.getOrderId()));
        itemService.saveBatch(orderItems);

        //扣减库存
        for (Long cartId : dto.getCartIds()) {
           if(!skuService.cutStock(cartId)){
               throw  BizExcept.erro("库存不足");
           }
        }

        //删除购物车id
        cartService.removeBatchByIds(dto.getCartIds());
        queue.offer(order.getOrderNo(),Constants.DELAY_TIME, TimeUnit.MINUTES);
        return order.getOrderNo();
    }

    @Override
    public PageBean<MiniappOrderVo> pageList(OrderPage dto) {
        if(dto.isPageShow()){
            PageHelper.startPage(dto.getPageNum(),dto.getPageSize());
        }
        LambdaQueryWrapper<PpOrder> queryWrapper= new LambdaQueryWrapper<PpOrder>().
                eq(PpOrder::getUserId,MiniappSessionUtil.getUserId())
                .eq(Objects.nonNull(dto.getStatus()),PpOrder::getStatus,dto.getStatus())
                .like(StrUtil.isNotBlank(dto.getName()),PpOrder::getNames,dto.getName());

        List<PpOrder> list = list(queryWrapper);
        for (PpOrder order : list) {
            for (PpOrder.ItemInfo itemInfo : order.getItemInfo()) {
                itemInfo.setCover(ossStore.getUrl(itemInfo.getCover()));
            }
        }
        return PageUtil.load(new PageInfo<>(list),MiniappOrderVo.class);
    }

    @Override
    @Transactional
    public void cancal(String orderNo) {
        //修改订单状态
        PpOrder order = getByOrderNo(orderNo);
        Assertion.nullThrow(order,"订单不存在");
        if(!order.getUserId().equals(MiniappSessionUtil.getUserId())){
            throw BizExcept.erro("订单不存在");
        }

        if(!Constants.orderToPayStatus.equals(order.getStatus())){
            throw BizExcept.erro("订单无法取消");
        }

        cancal(order);
    }

    @Override
    @Transactional
    public void sysCancal(String orderNo) {
        //修改订单状态
        PpOrder order = getByOrderNo(orderNo);
        //Assertion.nullThrow(order,"订单不存在");
        if(Objects.isNull(order)){
            return;
        }

        if(!Constants.orderToPayStatus.equals(order.getStatus())){
            //throw BizExcept.erro("订单无法取消");
            return;
        }

        cancal(order);
    }

    private void cancal(PpOrder order) {
        PpOrder editeOrder= new PpOrder();
        editeOrder.setOrderId(order.getOrderId());
        editeOrder.setStatus(Constants.orderCancelStatus);
        updateById(editeOrder);
        //回滚一下库存
        List<PpOrderItem> list = itemService
                .list(new LambdaQueryWrapper<PpOrderItem>().eq(PpOrderItem::getOrderId, order.getOrderId()));
        for (PpOrderItem item : list) {
            itemService.rollbackStock(item.getOrderItemId());
        }


        //微信支付的取消，关闭支付订单
        JsapiServiceExtension jsapi= new JsapiServiceExtension.Builder()
                .config(certificateConfig).build();

        CloseOrderRequest request= new CloseOrderRequest();
        request.setMchid(config.getMerchantId());
        request.setOutTradeNo(order.getOrderNo());
        jsapi.closeOrder(request);
    }

    @Override
    public PpOrder getByOrderNo(String orderNo) {
        return getOne(new LambdaQueryWrapper<PpOrder>().eq(PpOrder::getOrderNo,orderNo));
    }

    @Override
    public MiniappOrderDetailVo detail(String orderNo) {
        PpOrder order = getByOrderNo(orderNo);
        Assertion.nullThrow(order,"订单不存在");
        if(!Objects.equals(order.getUserId(),MiniappSessionUtil.getUserId())){
            Assertion.nullThrow(order,"订单不存在");
        }
        MiniappOrderDetailVo vo = BeanUtil.copyProperties(order, MiniappOrderDetailVo.class,"itemInfo");
        List<PpOrderItem> list = itemService.list(new LambdaQueryWrapper<PpOrderItem>()
                .eq(PpOrderItem::getOrderId, order.getOrderId()));
        list.forEach(e->{
            e.setCover(ossStore.getUrl(e.getCover()));
            e.setAttrInfoStr(CollUtil.join(e.getAttrInfo().values(),","));
        });
        vo.setItems(BeanUtil.copyToList(list,MiniappOrderItemVo.class));
        return vo;
    }

    @Override
    public List<Long> reorder(String orderNo) {
        PpOrder order = getByOrderNo(orderNo);
        Assertion.nullThrow(order,"订单不存在");
        if(!Objects.equals(order.getUserId(),MiniappSessionUtil.getUserId())){
            Assertion.nullThrow(order,"订单不存在");
        }

        List<PpOrderItem> list = itemService.list(new LambdaQueryWrapper<PpOrderItem>()
                .eq(PpOrderItem::getOrderId, order.getOrderId()));

        List<Long> cartIds= new ArrayList<>();
        for (PpOrderItem item : list) {
            CartAdd cartAdd= new CartAdd();
            cartAdd.setAmount(item.getAmount());
            cartAdd.setSkuId(item.getSkuId());
            cartAdd.setType(true);
            cartIds.add(cartService.add(cartAdd));
        }

        return cartIds;
    }
}
